package com.weixu.fileconver.service.impl;

import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.weixu.fileconver.entity.ConvertResult;
import com.weixu.fileconver.exception.FileConvertException;
import com.weixu.fileconver.service.FileConvertService;
import com.weixu.fileconver.util.LibreOfficeUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.*;
import java.nio.file.Files;

/**
 * 文件转换服务实现类
 *
 * @Author weixu
 * @Date 2025/8/29 上午10:04
 */
@Service
public class FileConvertServiceImpl implements FileConvertService {

    private static final Logger logger = LoggerFactory.getLogger(FileConvertServiceImpl.class);

    @Value("${file.temp-dir}")
    private String tempDir;

    @Resource
    private LibreOfficeUtil libreOfficeUtil;

    @Override
    public InputStream convertToFormat(MultipartFile file, String targetType) throws Exception {
        ConvertResult result = convertToFormatWithInfo(file, targetType);
        return result.getInputStream();
    }

    @Override
    public ConvertResult convertToFormatWithInfo(MultipartFile file, String targetType) throws Exception {
        // 参数校验
        if (file == null || file.isEmpty()) {
            throw new IllegalArgumentException("上传文件不能为空");
        }

        if (StrUtil.isBlank(targetType)) {
            throw new IllegalArgumentException("目标格式不能为空");
        }

        String originalFileName = file.getOriginalFilename();
        if (StrUtil.isBlank(originalFileName)) {
            throw new IllegalArgumentException("文件名不能为空");
        }

        // 验证目标格式是否支持
        if (!isSupportedtargetType(targetType)) {
            throw new IllegalArgumentException("不支持的目标格式: " + targetType);
        }

        // 验证格式转换兼容性
        if (!isConversionCompatible(originalFileName, targetType)) {
            String inputFormat = FileUtil.getSuffix(originalFileName);
            throw new IllegalArgumentException(String.format("不支持从 %s 格式转换为 %s 格式", inputFormat,
                    targetType));
        }

        // 检查文件格式是否支持
        if (!isSupportedFormat(originalFileName)) {
            throw new FileConvertException("不支持的文件格式: " + FileUtil.getSuffix(originalFileName));
        }

        // 检查LibreOffice是否可用
        if (!isLibreOfficeAvailable()) {
            throw new FileConvertException("LibreOffice不可用，请检查安装和配置");
        }

        logger.info("开始转换文件: {}, 大小: {} bytes", originalFileName, file.getSize());

        // 生成唯一的临时文件名
        String fileId = IdUtil.simpleUUID();
        String suffix = FileUtil.getSuffix(originalFileName);
        String inputFileName = fileId + (StrUtil.isNotBlank(suffix) ? "." + suffix : "");

        // 创建临时输入文件
        File tempInputFile = new File(tempDir, inputFileName);
        File convertedFile = null;

        try {
            // 确保临时目录存在
            FileUtil.mkdir(tempDir);

            // 保存上传的文件到临时目录
            file.transferTo(tempInputFile);

            logger.info("文件已保存到临时目录: {}", tempInputFile.getAbsolutePath());

            // 执行转换
            convertedFile = libreOfficeUtil.convertToFormat(tempInputFile, tempDir, targetType);

            logger.info("文件转换完成: {}", convertedFile.getAbsolutePath());

            // 读取转换后的文件为字节数组，然后创建ByteArrayInputStream
            byte[] fileBytes = Files.readAllBytes(convertedFile.toPath());
            InputStream inputStream = new ByteArrayInputStream(fileBytes);

            // 生成转换后的文件名
            String convertedFileName = FileUtil.getPrefix(originalFileName) + "." + targetType;
            String contentType = ConvertResult.getContentType(targetType);

            // 创建转换结果对象
            ConvertResult result = new ConvertResult(
                    inputStream,
                    convertedFileName,
                    contentType,
                    fileBytes.length,
                    originalFileName,
                    targetType
            );

            return result;

        } catch (IOException e) {
            logger.error("文件处理失败: {}", e.getMessage(), e);
            throw new FileConvertException("文件处理失败", e);
        } catch (Exception e) {
            logger.error("文件转换失败: {}", e.getMessage(), e);
            throw new FileConvertException("文件转换失败: " + e.getMessage(), e);
        } finally {
            // 清理临时文件
            if (tempInputFile != null && tempInputFile.exists()) {
                try {
                    FileUtil.del(tempInputFile);
                    logger.debug("已清理临时输入文件: {}", tempInputFile.getAbsolutePath());
                } catch (Exception e) {
                    logger.warn("清理临时输入文件失败: {}", e.getMessage());
                }
            }

            if (convertedFile != null && convertedFile.exists()) {
                try {
                    FileUtil.del(convertedFile);
                    logger.debug("已清理转换后文件: {}", convertedFile.getAbsolutePath());
                } catch (Exception e) {
                    logger.warn("清理转换后文件失败: {}", e.getMessage());
                }
            }
        }
    }

    @Override
    public boolean isSupportedFormat(String fileName) {
        return libreOfficeUtil.isSupportedFormat(fileName);
    }

    @Override
    public boolean isLibreOfficeAvailable() {
        return libreOfficeUtil.isLibreOfficeAvailable();
    }

    /**
     * 检查目标格式是否支持
     *
     * @param targetType 目标格式
     * @return 是否支持
     */
    private boolean isSupportedtargetType(String targetType) {
        // LibreOffice支持的输出格式
        String[] supportedFormats = {
                "pdf", "doc", "docx", "xls", "xlsx", "ppt", "pptx",
                "odt", "ods", "odp", "rtf", "txt", "html", "csv"
        };

        for (String format : supportedFormats) {
            if (format.equalsIgnoreCase(targetType)) {
                return true;
            }
        }
        return false;
    }

    /**
     * 检查格式转换兼容性
     *
     * @param inputFileName 输入文件名
     * @param targetType    目标格式
     * @return 是否兼容
     */
    private boolean isConversionCompatible(String inputFileName, String targetType) {
        String inputFormat = FileUtil.getSuffix(inputFileName).toLowerCase();
        String target = targetType.toLowerCase();

        // PDF格式转换支持
        if ("pdf".equals(inputFormat)) {
            // PDF可以转换为DOCX（使用writer_pdf_import过滤器）
            if ("docx".equals(target) || "doc".equals(target)||"html".equals(target)) {
                return true;
            }
            // PDF转换为其他格式暂不支持
            return false;
        }

        // 定义不兼容的转换组合
        // Excel文件转换限制
        if (("xls".equals(inputFormat) || "xlsx".equals(inputFormat)) &&
                ("doc".equals(target) || "docx".equals(target) || "ppt".equals(target) || "pptx".equals(target))) {
            return false;
        }

        // Word文件转换限制
        if (("doc".equals(inputFormat) || "docx".equals(inputFormat)) &&
                ("xls".equals(target) || "xlsx".equals(target) || "ppt".equals(target) || "pptx".equals(target))) {
            return false;
        }

        // PowerPoint文件转换限制
        if (("ppt".equals(inputFormat) || "pptx".equals(inputFormat)) &&
                ("xls".equals(target) || "xlsx".equals(target) || "doc".equals(target) || "docx".equals(target))) {
            return false;
        }

        // 所有格式都可以转换为PDF、HTML、TXT、RTF
        if ("pdf".equals(target) || "html".equals(target) || "txt".equals(target) || "rtf".equals(target)) {
            return true;
        }

        // 同类型格式之间可以转换
        if (("xls".equals(inputFormat) || "xlsx".equals(inputFormat)) &&
                ("xls".equals(target) || "xlsx".equals(target) || "csv".equals(target) || "ods".equals(target))) {
            return true;
        }

        if (("doc".equals(inputFormat) || "docx".equals(inputFormat)) &&
                ("doc".equals(target) || "docx".equals(target) || "odt".equals(target))) {
            return true;
        }

        if (("ppt".equals(inputFormat) || "pptx".equals(inputFormat)) &&
                ("ppt".equals(target) || "pptx".equals(target) || "odp".equals(target))) {
            return true;
        }

        // LibreOffice格式之间的转换
        if (("odt".equals(inputFormat) || "ods".equals(inputFormat) || "odp".equals(inputFormat)) &&
                ("odt".equals(target) || "ods".equals(target) || "odp".equals(target))) {
            return true;
        }

        return false;
    }
}
